1 \documentclass[10pt,letterpaper
]{article
}
3 %---------------------------------------------------------------
4 \usepackage[utf8
]{inputenc}
5 \usepackage[spanish
]{babel
}
7 \usepackage[usenames,dvipsnames
]{color}
12 %---------------------------------------------------------------
14 \setlength{\topmargin}{-
1.0in
}
15 \setlength{\textheight}{9.5in
}
16 \setlength{\evensidemargin}{0.0in
}
17 \setlength{\oddsidemargin}{0.0in
}
18 \setlength{\textwidth}{6.5in
}
22 %---------------------------------------------------------------
23 \title{Resumen de algoritmos para torneos de programación
}
27 %---------------------------------------------------------------
29 %---------------------------------------------------------------
32 \lstloadlanguages{C++
}
33 %---------------------------------------------------------------
34 %---------------------------------------------------------------
35 \section{Teoría de números
}
36 %---------------------------------------------------------------
38 \input{./src/number_theory/bigmod
}%.tex
40 \subsection{Criba de Eratóstenes
}
42 \textbf{Field-testing:
}
44 \item \emph{SPOJ
} -
2912 - Super Primes
45 \item \emph{Live Archive
} -
3639 - Prime Path
49 Marca los números primos en un arreglo. Algunos tiempos de ejecución:
53 SIZE & Tiempo (s) \\
[0.5ex
]
58 100000000 &
7.650 \\
[1ex
]
63 \input{./src/number_theory/criba
}%.tex
65 \subsection{Divisores de un número
}
66 Este algoritmo imprime todos los divisores de un número (en desorden) en O($
\sqrt{n
}$).
67 Hasta
4294967295 (máximo
\textit{unsigned long
}) responde instantaneamente. Se puede
68 forzar un poco más usando
\textit{unsigned long long
} pero más allá de $
10^
{12}$ empieza a
73 \input{./src/number_theory/divisores
}%.tex
75 \section{Combinatoria
}
76 \subsection{Cuadro resumen
}
77 Fórmulas para combinaciones y permutaciones:
79 \renewcommand{\arraystretch}{2} %Multiplica la altura de cada fila de la tabla por 2
80 %Si quiero aumentar el tamaño de una fila en particular insertar \rule{0cm}{1cm} en esa fila.
81 \begin{tabular
}{| c | c | c |
}
83 \textit{Tipo
} &
\textit{¿Se permite la repetición?
} &
\textit{Fórmula
} \\
[1.5ex
]
86 $r$-permutaciones & No & $
\displaystyle\frac{n!
}{(n-r)!
} $ \\
[1.5ex
]
88 $r$-combinaciones & No & $
\displaystyle\frac{n!
}{r!(n-r)!
} $ \\
[1.5ex
]
90 $r$-permutaciones & Sí & $
\displaystyle n^
{r
} $ \\
92 $r$-combinaciones & Sí & $
\displaystyle\frac{(n+r-
1)!
}{r!(n-
1)!
} $ \\
[1.5ex
]
95 \renewcommand{\arraystretch}{1}
97 Tomado de
\textit{Matemática discreta y sus aplicaciones
}, Kenneth Rosen,
5$
{}^
{\hbox{ta
}}$ edición, McGraw-Hill, página
315.
99 \subsection{Combinaciones, coeficientes binomiales, triángulo de Pascal
}
100 \emph{Complejidad:
} $ O(n^
2) $ \\
101 $$
{n
\choose k
} =
\left\
{
105 \displaystyle {n -
1 \choose k -
1} +
{n -
1 \choose k
} &
\mbox{en otro caso
}\\
110 \input{./src/combinatoria/pascal_triangle
}%.tex
113 \textbf{Nota:
} $
\displaystyle {n
\choose k
} $ está indefinido en el código anterior si $ n > k$. ¡La tabla puede estar llena con cualquier basura del compilador!
115 \subsection{Permutaciones con elementos indistinguibles
}
116 El número de permutaciones
\underline{diferentes
} de $n$ objetos, donde hay $n_
{1}$ objetos indistinguibles de tipo
1,
117 $n_
{2}$ objetos indistinguibles de tipo
2, ..., y $n_
{k
}$ objetos indistinguibles de tipo $k$, es
119 \frac{n!
}{n_
{1}!n_
{2}!
\cdots n_
{k
}!
}
121 \textbf{Ejemplo:
} Con las letras de la palabra
\texttt{PROGRAMAR
} se pueden formar $
\displaystyle \frac{9!
}{2!
\cdot 3!
} =
122 30240 $ permutaciones
\underline{diferentes
}.
123 \subsection{Desordenes, desarreglos o permutaciones completas
}
125 Un desarreglo es una permutación donde ningún elemento $i$ está en la
126 posición $i$-ésima. Por ejemplo,
\textit{4213} es un desarreglo de
4 elementos pero
127 \textit{3241} no lo es porque el
2 aparece en la posición
2.
129 Sea $D_
{n
}$ el número de desarreglos de $n$ elementos, entonces:
134 (n-
1)(D_
{n-
1} + D_
{n-
2}) & n
\geq 2\\
138 Usando el principio de inclusión-exclusión, también se puede encontrar la fórmula
140 D_
{n
} = n!
\left [ 1 -
\frac{1}{1!
} +
\frac{1}{2!
} -
\frac{1}{3!
} +
\cdots + (-
1)^
{n
}\frac{1}{n!
} \right ]
141 = n!
\sum_{i=
0}^
{n
} \frac{(-
1)^
{i
}}{i!
}
145 \subsection{Algoritmo de Dijkstra
}
146 El peso de todas las aristas debe ser no negativo.
148 \input{./src/grafos/dijkstra
}%.tex
150 \subsection{Minimum spanning tree: Algoritmo de Prim
}
152 \input{./src/grafos/prim
}%.tex
154 \subsection{Minimum spanning tree: Algoritmo de Kruskal + Union-Find
}
155 \input{./src/grafos/kruskal
}%.tex
157 \subsection{Algoritmo de Floyd-Warshall
}
158 \emph{Complejidad:
} $ O(n^
3) $ \\
159 Se asume que no hay ciclos de costo negativo.
160 \input{./src/grafos/floyd
}%.tex
162 \subsection{Algoritmo de Bellman-Ford
}
163 Si no hay ciclos de coste negativo, encuentra la distancia más corta entre un nodo
164 y todos los demás. Si sí hay, permite saberlo. \\
165 El coste de las aristas
\underline{sí
} puede ser negativo.
166 \input{./src/grafos/bellman
}%.tex
168 \subsection{Puntos de articulación
}
169 \input{./src/grafos/puntos_articulacion
}%.tex
171 \subsection{Máximo flujo: Método de Ford-Fulkerson, algoritmo de Edmonds-Karp
}
172 El algoritmo de Edmonds-Karp es una modificación al método de Ford-Fulkerson. Este último
173 utiliza DFS para hallar un camino de aumentación, pero la sugerencia de Edmonds-Karp
174 es utilizar BFS que lo hace más eficiente en algunos grafos.
177 \input{./src/grafos/ford_fulkerson
}%.tex
179 \section{Programación dinámica
}
180 \subsection{Longest common subsequence
}
181 \input{./src/dp/lcs
}%.tex
183 \subsection{Partición de troncos
}
184 Este problema es similar al problema de
\textit{Matrix Chain Multiplication
}. Se tiene
185 un tronco de longitud $n$, y $m$ puntos de corte en el tronco. Se puede hacer un corte a la vez,
186 cuyo costo es igual a la longitud del tronco. ¿Cuál es el mínimo costo para partir todo el tronco
187 en pedacitos individuales?
190 \textbf{Ejemplo:
} Se tiene un tronco de longitud
10. Los puntos de corte son
2,
4, y
7. El mínimo
191 costo para partirlo es
20, y se obtiene así:
193 \item Partir el tronco (
0,
10) por
4. Vale
10 y quedan los troncos (
0,
4) y (
4,
10).
194 \item Partir el tronco (
0,
4) por
2. Vale
4 y quedan los troncos (
0,
2), (
2,
4) y (
4,
10).
195 \item No hay que partir el tronco (
0,
2).
196 \item No hay que partir el tronco (
2,
4).
197 \item Partir el tronco (
4,
10) por
7. Vale
6 y quedan los troncos (
4,
7) y (
7,
10).
198 \item No hay que partir el tronco (
4,
7).
199 \item No hay que partir el tronco (
7,
10).
200 \item El costo total es $
10+
4+
6 =
20$.
204 El algoritmo es $O(n^
3)$, pero optimizable a $O(n^
2)$ con una tabla adicional:
205 \input{./src/dp/particion_troncos
}%.tex
208 \subsection{Área de un polígono
}
209 Si P es un polígono simple (no se intersecta a sí mismo) su área está dada por: \\
211 $ A(P) =
\frac{1}{2} \displaystyle\sum_{i=
0}^
{n-
1} (x_
{i
} \cdot y_
{i+
1} - x_
{i+
1} \cdot y_
{i
}) $ \\
213 \input{./src/geometria/polygon_area
}%.tex
215 \subsection{Centro de masa de un polígono
}
216 Si P es un polígono simple (no se intersecta a sí mismo) su centro de masa está dado por: \\
218 $
\displaystyle\bar{C
}_
{x
} =
\frac{ \displaystyle\iint_{R
} x \, dA
}{M
} =
\frac{1}{6M
}\sum_{i=
1}^
{n
} (y_
{i+
1} - y_
{i
}) (x_
{i+
1}^
2 + x_
{i+
1} \cdot x_
{i
} + x_
{i
}^
2) $
222 $
\displaystyle\bar{C
}_
{y
} =
\frac{ \displaystyle\iint_{R
} y \, dA
}{M
} =
\frac{1}{6M
} \sum_{i=
1}^
{n
} (x_
{i
} - x_
{i+
1}) (y_
{i+
1}^
2 + y_
{i+
1} \cdot y_
{i
} + y_
{i
}^
2)$
226 Donde $ M $ es el área del polígono. \\
228 Otra posible fórmula equivalente:
230 $
\displaystyle\bar{C
}_
{x
} =
\frac{1}{6A
} \sum_{i=
0}^
{n-
1} (x_
{i
} + x_
{i+
1}) (x_
{i
} \cdot y_
{i+
1} - x_
{i+
1} \cdot y_
{i
}) $
234 $
\displaystyle\bar{C
}_
{y
} =
\frac{1}{6A
} \sum_{i=
0}^
{n-
1} (y_
{i
} + y_
{i+
1}) (x_
{i
} \cdot y_
{i+
1} - x_
{i+
1} \cdot y_
{i
}) $
237 \subsection{Convex hull: Graham Scan
}
238 \emph{Complejidad:
} $ O(n
\log_{2}{n
}) $
239 \input{./src/geometria/grahamscan
}%.tex
241 \subsection{Convex hull: Andrew's monotone chain
}
242 \emph{Complejidad:
} $ O(n
\log_{2}{n
}) $
243 \input{./src/geometria/monotonechain
}%.tex
245 \subsection{Mínima distancia entre un punto y un segmento
}
246 \input{./src/geometria/distance_point_to_segment
}%.tex
248 \subsection{Mínima distancia entre un punto y una recta
}
249 \input{./src/geometria/distance_point_to_line
}%.tex
251 \subsection{Determinar si un polígono es convexo
}
252 \input{./src/geometria/is_convex_polygon
}%.tex
254 \subsection{Determinar si un punto está dentro de un polígono convexo
}
255 \input{./src/geometria/is_inside_convex_polygon
}%.tex
257 \subsection{Determinar si un punto está dentro de un polígono cualquiera
}
258 \large{\textbf{ADVERTENCIA:
}} Código no probado.
259 \input{./src/geometria/is_inside_concave_polygon
}%.tex
261 %---------------------------------------------------------------
263 \subsection{El
\textit{parser
} más rápido del mundo
}
265 \item Cada no-terminal: un método
266 \item Cada lado derecho: invocar los métodos de los no-terminales o
267 \item Cada terminal: invocar proceso
\textit{match
}
268 \item Alternativas en una producción: se hace un
\textit{if
}
271 No funciona con gramáticas recursivas por izquierda ó en las que en algún momento haya
272 varias posibles escogencias que empiezan por el mismo caracter (En ambos casos la gramática se puede factorizar).
275 \textbf{Ejemplo:
} Para la gramática:
277 A
\longrightarrow (A)A
279 A
\longrightarrow \epsilon
282 \input{./src/misc/parser_recursivo_desc
}%.tex
286 \subsection{Entrada desde entrada estándar
}
287 Este primer método es muy fácil pero es mucho más ineficiente porque utiliza Scanner en vez de BufferedReader: \\
288 \input{./src/java/io_estandar_easy
}%.tex
292 Este segundo es más rápido: \\
293 \input{./src/java/io_estandar
}%.tex
294 \subsection{Entrada desde archivo
}
295 \input{./src/java/io_file
}%.tex
297 \subsection{Mapas y sets
}
299 \input{./src/java/maps_sets
}%.tex
301 La salida de este programa es: \\
304 \fbox{\parbox{2.0in
}{
319 \\
\normalfont\normalsize
321 Si quiere usarse una clase propia como llave del mapa o como elemento del set, la clase debe implementar
322 algunos métodos especiales: Si va a usarse un TreeMap ó TreeSet hay que implementar los métodos
\texttt{compareTo
} y
323 \texttt{equals
} de la interfaz
\texttt{Comparable
} como en la sección
\ref{colas_de_prioridad_java
}. Si va a usarse
324 un HashMap ó HashSet hay más complicaciones.\\
326 \textbf{Sugerencia:
} Inventar una manera de codificar y decodificar la clase en una String o un Integer y meter esa representación en el mapa o set: esas clases ya tienen los métodos implementados.
328 \subsection{Colas de prioridad
}
329 \label{colas_de_prioridad_java
}
330 Hay que implementar unos métodos. Veamos un ejemplo: \\
331 \input{./src/java/priority_queue
}%.tex
333 La salida de este programa es: \\
336 \fbox{\parbox{2.0in
}{
337 peso =
0, destino =
12\\
338 peso =
0, destino =
8\\
339 peso =
0, destino =
13\\
340 peso =
3, destino =
7\\
341 peso =
1876, destino =
4\\
344 \\
\normalfont\normalsize
346 Vemos que la función de comparación que definimos no tiene en cuenta
\texttt{destino
},
347 por eso no desempata cuando dos
\texttt{Items
} tienen el mismo
\texttt{peso
} si no que escoge
348 cualquiera de manera arbitraria.
351 \subsection{Entrada desde archivo
}
352 \input{./src/c++/io_file
}%.tex
354 \subsection{Strings con caractéres especiales
}
355 \input{./src/c++/unicode
}%.tex
357 \emph{Nota
}: Como alternativa a la función getline, se pueden utilizar las funciones fgetws y fputws, y más adelante swscanf y wprintf:
358 \input{./src/c++/fgetws
}%.tex